package com.mwy.auto;

import ws.schild.jave.*;

import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.channels.FileChannel;

public class PressAudio {
    /**
     * 传远程视频连接，返回压缩后File
     */
    public static File compressionVideo(String href){
        try{
            // 缓存到临时目录，压缩上传完到远程服务器上之后，记得删除源视频
            String savePath = "tmp/tempVideo/";
            long time = System.currentTimeMillis();
            URL url=new URL(href);
            HttpURLConnection connection=(HttpURLConnection)url.openConnection();
            connection.setConnectTimeout(600*1000);
            connection.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36");
            InputStream in=connection.getInputStream();
            String fileName =  "zip" + href.substring(href.lastIndexOf("/") + 1);
            File saveDir = new File(savePath);
            if(!saveDir.exists()){
                saveDir.mkdirs();
            }
            File file = new File(savePath + fileName);
            OutputStream out=new FileOutputStream(file);
            byte[] bytes=new byte[1024];
            int len = 0;
            while((len=in.read(bytes))!=-1){
                out.write(bytes,0,len);
            }
            out.close();
            in.close();
            System.out.println("下载+压缩 总耗时：" + (System.currentTimeMillis() - time)/1000);
            return compressionVideo(file, fileName);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 传视频File对象，返回压缩后File对象信息
     * @param source  传入的视频对象  File source = new File("视频文件所在位置");
     * @param picName 压缩后文件的文件名  (包括后缀名 比如：  demo.mp4,hello.avi等)
     */
    public static File compressionVideo(File source,String picName) {
        if(source == null){
            return null;
        }
        //新文件路径
        String newPath = "temp/audio/"+picName;
        //获取源文件路径，拼接压缩文件名
//        String newPath = source.getAbsolutePath().substring(0, source.getAbsolutePath().lastIndexOf("\\")).concat(picName);
        File target = new File(newPath);
        try {
            long time3 = System.currentTimeMillis();
            MultimediaObject object = new MultimediaObject(source);     //以源文件作为参数创建多媒体对象
            long time4 = System.currentTimeMillis();
            System.out.println("读取源文件时间："+(time4-time3));
            AudioInfo audioInfo = object.getInfo().getAudio();         //由多媒体对象获得其中的音频信息（差不多花2秒左右，不随文件大小变化）
            long time5 = System.currentTimeMillis();
            System.out.println("获得音频对象时间："+(time5-time4));
            // 根据视频大小来判断是否需要进行压缩,
            int maxSize = 100;
            //传入视频文件的大小，这里单位是兆M
            double mb = Math.ceil(source.length()/ 1048576);
            //传入视频的时长（播放时间），单位：秒
            object.getInfo().getDuration();
            long time6 = System.currentTimeMillis();
            System.out.println("获取视频时长时间："+(time6-time5));
            int second = (int)object.getInfo().getDuration()/1000;    // 大概会花费1秒多
            //文件大小 / 时长= 平均每秒中文件所占大小，并格式化，4位小数
            BigDecimal bd = new BigDecimal(String.format("%.4f", mb/second));
            System.out.println("开始压缩视频了--> 视频每秒平均 "+ bd +" MB ");
            // 视频 > 100MB, 或者每秒 > 0.5 MB 才做压缩， 不需要的话可以把判断去掉
            boolean temp = mb > maxSize || bd.compareTo(new BigDecimal(0.5)) > 0;
            if(true){
                long time = System.currentTimeMillis();    //开始时间
                //TODO 音频属性设置
                int maxBitRate = 128000;       //设置最大比特率
                int maxSamplingRate = 44100;  //设置最大采样率
                int bitRate = 800000;        //设置比特率
                int maxFrameRate = 20;       //设置最大帧数率
                int maxWidth = 1280;         //设置最大宽度

                AudioAttributes audio = new AudioAttributes();   //音频属性实体类
                audio.setCodec("aac");                  // 设置通用编码格式
                // 设置最大值：比特率越高，清晰度/音质越好
                // 设置音频比特率,单位:b (比特率越高，清晰度/音质越好，当然文件也就越大 128000 = 182kb)
                if(audioInfo.getBitRate() > maxBitRate){
                    audio.setBitRate(new Integer(maxBitRate));
                }
                // 设置重新编码的音频流中使用的声道数（1 =单声道，2 = 双声道（立体声））。如果未设置任何声道值，则编码器将选择默认值 0。
                audio.setChannels(audioInfo.getChannels());    //这里表示和原来设置相同
                // 采样率越高声音的还原度越好，文件越大
                // 设置音频采样率，单位：赫兹 hz
                // 设置编码时候的音量值，未设置为0,如果256，则音量值不会改变
                // audio.setVolume(256);
                if(audioInfo.getSamplingRate() > maxSamplingRate){
                    audio.setSamplingRate(maxSamplingRate);
                }



                //TODO 视频属性配置
                VideoInfo videoInfo = object.getInfo().getVideo();       //由多媒体对象获得视频信息实体类（差不多花2秒左右，不随文件大小变化）
                long time7 = System.currentTimeMillis();
                System.out.println("获得视频属性时间："+(time7-time6));
                VideoAttributes video = new VideoAttributes();          //视频属性实体类
                video.setCodec("h264");                           // 设置编码格式
                //设置视频比特率,单位:b (比特率越高，清晰度/音质越好，当然文件也就越大 800000 = 800kb)
                if(videoInfo.getBitRate() > bitRate){
                    video.setBitRate(bitRate);
                }

                // 视频帧率：15 f / s  帧率越低，效果越差
                // 设置视频帧率（帧率越低，视频会出现断层，越高让人感觉越连续），视频帧率（Frame rate）是用于测量显示帧数的量度。所谓的测量单位为每秒显示帧数(Frames per Second，简：FPS）或“赫兹”（Hz）。
                if(videoInfo.getFrameRate() > maxFrameRate){
                    video.setFrameRate(maxFrameRate);
                }

                // 限制视频宽高
                int width = videoInfo.getSize().getWidth();
                int height = videoInfo.getSize().getHeight();
                if(width > maxWidth){
                    float rat = (float) width / maxWidth;   //缩小比
                    video.setSize(new VideoSize(maxWidth,(int)(height/rat)));
                }
                long time8 = System.currentTimeMillis();
                System.out.println("设置视频属性时间："+(time8-time7));
                EncodingAttributes attr = new EncodingAttributes();    //编码属性实体类
                attr.setFormat("mp4");                                 //设置视频格式
                attr.setAudioAttributes(audio);                        //设置视频文件的音频属性（在上面有具体设置）
                attr.setVideoAttributes(video);                        //设置视频文件的视频属性（在上面有具体设置）
                long time9 = System.currentTimeMillis();
                System.out.println("设置编码属性时间："+(time9-time8));
                // 速度最快的压缩方式， 压缩速度 从快到慢： ultrafast, superfast, veryfast, faster, fast, medium,  slow, slower, veryslow and placebo.
//                attr.setPreset(PresetUtil.VERYFAST);
//                attr.setCrf(27);
//                // 设置编码线程数
//                attr.setEncodingThreads(Runtime.getRuntime().availableProcessors()/2);

                Encoder encoder = new Encoder();    //编码器
                long time1 = System.currentTimeMillis();
                System.out.println("new一个编码器时间："+(time9-time1));
                encoder.encode(new MultimediaObject(source), target, attr);   //压缩时间，最费时间的一步
                long time2 = System.currentTimeMillis();
                System.out.println("编码时间："+(time2-time1));
                System.out.println("压缩总耗时：" + (System.currentTimeMillis() - time)/1000);
                return target;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //如果压缩成功，删除源文件，如果不需要删除，可以去掉这段代码
//            if(target.length() > 0){
//                source.delete();
//            }
        }
        return source;
    }

    /**
     * 获取视频大小
     * @param source
     * @return
     */
    @SuppressWarnings({ "resource" })
    public static BigDecimal ReadVideoSize(File source) {
        FileChannel fc = null;
        try {
            FileInputStream fis = new FileInputStream(source);
            fc = fis.getChannel();
            BigDecimal fileSize = new BigDecimal(fc.size());
            return fileSize.divide(new BigDecimal(1048576), 2, RoundingMode.HALF_UP);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != fc) {
                try {
                    fc.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    //测试
    public static void main(String[] args) throws Exception{
        //测试远程下载视频并压缩
//        File file = PressAudio.compressionVideo("https://vd4.bdstatic.com/mda-mb3ew02ywud6xupd/sc/cae_h264_clips/1612407141/mda-mb3ew02ywud6xupd.mp4");
//        System.out.println(file.getName());


        //压缩视频
        File source = new File("D:\\tmp\\tempVideo\\ani.flv");
        File file = compressionVideo(source, source.getName());
        System.out.println(file.getName());
    }
}